package com.tbl.modules.wms2.controller.operation;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.plugins.Page;
import com.tbl.modules.platform.controller.AbstractController;
import com.tbl.modules.wms.dao.baseinfo.WarehouseDAO;
import com.tbl.modules.wms.dao.interfacelog.InterfaceLogDAO;
import com.tbl.modules.wms.entity.baseinfo.Warehouse;
import com.tbl.modules.wms2.constant.Constant;
import com.tbl.modules.wms2.dao.baseinfo.OrganizeDao;
import com.tbl.modules.wms2.dao.baseinfo.YclInventoryDAO;
import com.tbl.modules.wms2.dao.operation.OperationOtherMapper;
import com.tbl.modules.wms2.entity.baseinfo.YclInventory;
import com.tbl.modules.wms2.entity.operation.OperationOther;
import com.tbl.modules.wms2.entity.operation.OperationOtherHeadDTO;
import com.tbl.modules.wms2.entity.operation.OperationOtherLine;
import com.tbl.modules.wms2.entity.operation.OperationOtherLineDTO;
import com.tbl.modules.wms2.entity.operation.OperationOtherPrint;
import com.tbl.modules.wms2.entity.operation.OperationOtherProcessDTO;
import com.tbl.modules.wms2.entity.operation.OperationOtherVO;
import com.tbl.modules.wms2.entity.operation.OperationOtherValidDTO;
import com.tbl.modules.wms2.entity.operation.YclInOutFlowEntity;
import com.tbl.modules.wms2.entity.report.YclInventoryEntity;
import com.tbl.modules.wms2.service.common.CountService;
import com.tbl.modules.wms2.service.operation.OperationOtherLineService;
import com.tbl.modules.wms2.service.operation.OperationOtherService;
import com.tbl.modules.wms2.service.operation.YclInOutFlowService;
import com.tbl.modules.wms2.service.report.InventoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.validation.constraints.NotEmpty;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 其他出入库管理
 *
 * @author Sweven
 * @date 2020-06-25
 */
@Validated
@Controller
@RequestMapping("/ycl/operation/other")
public class OperationOtherController extends AbstractController {

    @Autowired
    private OperationOtherService otherService;
    @Resource
    private OperationOtherMapper otherMapper;
    @Autowired
    private OperationOtherLineService otherLineService;
    @Autowired
    private CountService countService;
    @Autowired
    private InventoryService inventoryService;
    @Resource
    private YclInOutFlowService yclInOutFlowService;
    @Autowired
    private OrganizeDao organizeDao;
    @Autowired
    private WarehouseDAO warehouseDAO;
    @Autowired
    private YclInventoryDAO inventoryDAO;
    /** 接口日志 */
    @Autowired
    private InterfaceLogDAO interfaceLogDAO;

    /**
     * 跳转至列表页
     *
     * @return
     */
    @RequestMapping("/toList")
    public ModelAndView toRewindList() {
        ModelAndView mv = this.getModelAndView();
        mv.setViewName("techbloom2/operationOther/list");
        return mv;
    }

    /**
     * 获取Grid列表数据
     *
     * @return Map<String, Object>
     */
    @RequestMapping(value = "/list")
    @ResponseBody
    public Map<String, Object> list() {
        Map<String, Object> paramsMap = getAllParameter();
        List<OperationOtherVO> pageList = otherService.getPageList(
                new Page<>(Integer.parseInt((String)paramsMap.get("page")),
                           Integer.parseInt((String)paramsMap.get("limit"))), paramsMap);
        Map<String, Object> map = new HashMap<>(4);
        map.put("code", 0);
        map.put("msg", null);
        map.put("count", otherMapper.count(paramsMap));
        map.put("data", pageList);
        return map;
    }

    /**
     * 获取Grid列表数据——手机端
     *
     * @return Map<String, Object>
     */
    @GetMapping(value = "/api/list")
    @ResponseBody
    public Map<String, Object> listApi() {
        Map<String, Object> paramsMap = getAllParameter();
        List<OperationOtherVO> pageList = otherService.getPageListApi(
                new Page<>(Integer.parseInt((String)paramsMap.get("page")),
                           Integer.parseInt((String)paramsMap.get("limit"))), paramsMap);
        Map<String, Object> map = new HashMap<>(4);
        map.put("code", 0);
        map.put("msg", null);
        map.put("count", otherMapper.countApi(paramsMap));
        map.put("data", pageList);
        return map;
    }

    /**
     * 跳转编辑页
     *
     * @return
     */
    @RequestMapping(value = "/toEdit")
    public ModelAndView toEdit() {
        ModelAndView mv = this.getModelAndView();
        mv.setViewName("techbloom2/operationOther/edit");
        return mv;
    }

    /**
     * 提交Grid列表数据
     *
     * @return Map<String, Object>
     */
    @PostMapping(value = "/push")
    @ResponseBody
    @Transactional
    public Map<String, Object> push(@RequestBody OperationOther other) {
        Map<String, Object> map = MapUtil.newHashMap(2);
        try {
            if ("1".equals(other.getBusinessType())) {
                AtomicInteger lineNum = new AtomicInteger();
                for (OperationOtherLine otherLine : other.getLineList()) {
                    YclInventoryEntity entity = inventoryService.find(other.getAreaCode(), other.getStoreCode(),
                            otherLine.getLocatorCode(),
                            otherLine.getMaterialCode(), otherLine.getLotsNum());
                    if (ObjectUtil.isNull(entity)) {
                        map.put("code", 1);
                        map.put("msg", StrUtil.format("行号【{}】未查询到库存", lineNum.incrementAndGet()));
                        return map;
                    }
                    if (otherLine.getQuantity().compareTo(entity.getQuality()) > 0) {
                        map.put("code", 1);
                        map.put("msg",
                                StrUtil.format("行号【{}】数量大于库存数量，当前库存数量：{}", lineNum.incrementAndGet(), entity.getQuality()));
                        return map;
                    }
                    lineNum.incrementAndGet();
                }
            }
            // Map<String, List<OperationOtherLine>> collect = other.getTableList().stream().collect(
            //         Collectors.groupingBy(OperationOtherLine::getMaterialCode));
            // for (String s : collect.keySet()) {
            //     BigDecimal totalOrderQuantity = new BigDecimal("0");
            //     List<OperationOtherLine> otherLines = collect.get(s);
            //     for (OperationOtherLine otherLine : otherLines) {
            //         totalOrderQuantity = totalOrderQuantity.add(otherLine.getQuantity());
            //     }
            //     OperationOtherLine otherLine = otherLines.get(0);
            //     int i = totalOrderQuantity.compareTo(otherLine.getOrderQuantity());
            //     if (i != 0) {
            //         map.put("code", 1);
            //         map.put("msg", StrUtil.format("物料编码【{}】订单数量不等于数量之和", s));
            //         return map;
            //     }
            // }
            // String otherCode = RandomUtil.randomString(8);

            Map<String, Object> objectMap = MapUtil.newHashMap(2);
            objectMap.put("storeCode", other.getStoreCode());
            objectMap.put("entityId", other.getAreaCode());
            Long organizationId = Long.valueOf(organizeDao.selectOrganization(objectMap).get(0).get("id").toString());
            String otherCode = countService.getNextCount("QTCRK");
            other.setOtherCode(otherCode);
            other.setOrganizationId(organizationId);
            other.setCreatorId(getUserId().toString());
            other.setCreator(getSessionUser().getName());
            other.setWorkNo(getSessionUser().getUsername());
            AtomicInteger line = new AtomicInteger();
            List<OperationOtherLine> lineList = other.getLineList().stream().peek(otherLine -> {
                otherLine.setOtherCode(otherCode);
                otherLine.setLineCode(String.valueOf(line.incrementAndGet()));
                otherLine.setState("1");
            }).collect(Collectors.toList());

            Warehouse warehouse = warehouseDAO.findByCodeAndEntityId(other.getStoreCode(), other.getAreaCode());
            if (ObjectUtil.isNull(warehouse) || ObjectUtil.isNull(warehouse.getLocatorId())) {
                map.put("code", 1);
                map.put("msg", "EBS虚拟库位不存在，请检查！");
                return map;
            }

            OperationOtherHeadDTO headDTO = new OperationOtherHeadDTO();
            headDTO.setOrganizationId(other.getOrganizationId());
            headDTO.setBusinessType(other.getBusinessType().equals("1") ? "OUTBOND" : "INBOND");
            headDTO.setBusinessPurpose(other.getBusinessPurposeName());
            headDTO.setDepartCode(other.getManufacturer());
            headDTO.setOperationSeqNum(other.getProcess());
            headDTO.setOperationMachine(other.getMachine());
            headDTO.setPreparer(other.getWorkNo());
            headDTO.setRemark(other.getRemark());
            headDTO.setUser(other.getWorkNo());
            headDTO.setLyytCode(other.getEffect());
            headDTO.setLoad(other.getCarInfo());
            headDTO.setVendorName(other.getSupplierCode());
            String request = JSONObject.toJSONString(headDTO);
            otherService.createHead(headDTO);
            interfaceLogDAO.insertLog("apps.cux_wms_inv_misctx_pkg.create_head", "创建或更新其他出入库头信息",
                                      request, JSONObject.toJSONString(headDTO), other.getOtherCode(), "");
            if (headDTO.getRetCode().equals(Constant.ERROR)) {
                map.put("code", 1);
                map.put("msg", headDTO.getRetMess());
                return map;
            }
            for (OperationOtherLine otherLine : lineList) {
                OperationOtherLineDTO lineDTO = new OperationOtherLineDTO();
                lineDTO.setHeadId(headDTO.getHeadId());
                lineDTO.setOrganizationId(headDTO.getOrganizationId());
                lineDTO.setLineNum(Long.valueOf(otherLine.getLineCode()));
                lineDTO.setMaterialCode(otherLine.getMaterialCode());
                lineDTO.setPrimaryUnit(otherLine.getPrimaryUnit());
                lineDTO.setTransactionQuantity(otherLine.getQuantity());
                lineDTO.setSubCode(other.getStoreCode());
                lineDTO.setLocator(warehouse.getLocatorId());
                lineDTO.setRemark(otherLine.getRemark());
                lineDTO.setTransferSubCode(other.getStoreCode());
                lineDTO.setTransferLocator(warehouse.getLocatorId());
                lineDTO.setUser(headDTO.getUser());
                String request1 = JSONObject.toJSONString(lineDTO);
                otherService.createLine(lineDTO);
                interfaceLogDAO.insertLog("apps.cux_wms_inv_misctx_pkg.create_line", "创建/更新其他出入库行信息", request1,
                                          JSONObject.toJSONString(lineDTO), other.getOtherCode(), otherLine.getLotsNum());
                if (lineDTO.getRetCode().equals(Constant.ERROR)) {
                    map.put("code", 1);
                    map.put("msg", lineDTO.getRetMess());
                    return map;
                }
                OperationOtherValidDTO validDTO = new OperationOtherValidDTO();
                validDTO.setHeadId(lineDTO.getHeadId());
                String request2 = JSONObject.toJSONString(validDTO);
                otherService.validateData(validDTO);
                interfaceLogDAO.insertLog("apps.cux_wms_inv_misctx_pkg.validate_data", "其他出入库数据校验", request2,
                                          JSONObject.toJSONString(validDTO), other.getOtherCode(), "");
                if (validDTO.getRetCode().equals(Constant.ERROR)) {
                    map.put("code", 1);
                    map.put("msg", validDTO.getRetMess());
                    return map;
                }
                OperationOtherProcessDTO processDTO = new OperationOtherProcessDTO();
                processDTO.setHeadId(lineDTO.getHeadId());
                processDTO.setLineId(lineDTO.getLineId());
                String request3 = JSONObject.toJSONString(processDTO);
                otherService.process(processDTO);
                interfaceLogDAO.insertLog("apps.cux_wms_inv_misctx_pkg.process", "其他出入库事务处理", request3,
                                          JSONObject.toJSONString(processDTO), other.getOtherCode(), "");
                if (processDTO.getRetCode().equals(Constant.ERROR)) {
                    map.put("code", 1);
                    map.put("msg", processDTO.getRetMess());
                    return map;
                }
            }

            otherService.insertAllColumn(other);
            otherLineService.insertBatch(lineList, lineList.size());

            for (OperationOtherLine otherLine : lineList) {
                YclInOutFlowEntity yclInOutFlowEntity = new YclInOutFlowEntity();
                yclInOutFlowEntity.setPrimaryUnit(otherLine.getPrimaryUnit());
                yclInOutFlowEntity.setMaterialName(otherLine.getMaterialName());
                yclInOutFlowEntity.setStoreCode(other.getStoreCode());
                yclInOutFlowEntity.setAreaCode(other.getAreaCode());
                yclInOutFlowEntity.setLocatorCode(otherLine.getLocatorCode());
                yclInOutFlowEntity.setMaterialCode(otherLine.getMaterialCode());
                yclInOutFlowEntity.setLotsNum(otherLine.getLotsNum());
                yclInOutFlowEntity.setUpdownQuantity(otherLine.getQuantity());
                yclInOutFlowEntity.setInoutType("1".equals(other.getBusinessType()) ? "0" : "1");
                yclInOutFlowEntity.setCreateTime(DateUtil.date());
                yclInOutFlowEntity.setCreateUser(getSessionUser().getUsername());
                yclInOutFlowService.save(yclInOutFlowEntity);
            }
        }catch (Exception e){
            e.printStackTrace();
            String request1 = JSONObject.toJSONString(other);
            interfaceLogDAO.insertLog("/ycl/operation/other/push", "其他出入库提交报错", request1, request1,
                                      other.getOtherCode(), "");
            throw e;
        }
        map.put("code", 0);
        map.put("msg", "提交成功");
        return map;
    }

    /**
     * 打印页面
     *
     * @return
     */
    @RequestMapping("/toPrint")
    @ResponseBody
    public ModelAndView toPrint(String otherCode) {
        ModelAndView mv = this.getModelAndView();
        mv.setViewName("techbloom2/operationOther/print");
        OperationOtherPrint other = otherService.findByOtherCode(otherCode);
        // List<OperationOtherLine> otherLines = otherLineService.findByOtherCode(otherCode);
        // other.setTableList(otherLines);
        mv.addObject("other", other);
        mv.addObject("operator", getSessionUser().getName());
        // mv.addObject("otherCode", otherCode);
        return mv;
    }

    /**
     * 打印页面
     *
     * @return
     */
    @RequestMapping("/printData")
    @ResponseBody
    public Map<String, Object> printData(String otherCode) {
        // OperationOtherPrint other = otherService.findByOtherCode(otherCode);
        List<OperationOtherLine> otherLines = otherLineService.findByOtherCode(otherCode);
        // other.setTableList(otherLines);
        Map<String, Object> map = new HashMap<>(2);
        map.put("code", 0);
        map.put("data", otherLines);
        return map;
    }

    /**
     * 打印出厂单
     *
     * @return
     */
    @RequestMapping("/toPrintOut")
    @ResponseBody
    public Map<String, Object> toPrintOut(String otherCode) {
        OperationOtherPrint other = otherService.findByOtherCode(otherCode);
        List<OperationOtherLine> otherLines = otherLineService.findByOtherCode(otherCode);
        other.setLineList(otherLines);
        Map<String, Object> map = new HashMap<>(2);
        map.put("code", 0);
        map.put("data", other);
        return map;
    }

    /**
     * 获取详情——手机端
     *
     * @return
     */
    @GetMapping("/api/detail")
    @ResponseBody
    public Map<String, Object> detailApi(
            @RequestParam(name = "otherCode", required = false, defaultValue = "") @NotEmpty(message = "单据编号不能为空") String otherCode) {
        OperationOtherPrint other = otherService.findByOtherCode(otherCode);
        List<OperationOtherLine> otherLines = otherLineService.findByOtherCode(otherCode);
        other.setLineList(otherLines);
        Map<String, Object> map = new HashMap<>(2);
        map.put("code", 0);
        map.put("data", other);
        return map;
    }

    /**
     * 根据仓库、厂区、批次号获取物料信息——手机端
     *
     * @return
     */
    @GetMapping("/api/inventory")
    @ResponseBody
    public Map<String, Object> inventory(YclInventory inventory) {
        List<YclInventory> inventoryList = inventoryDAO.findByLotsNum(inventory);
        Map<String, Object> map = new HashMap<>(2);
        map.put("code", 0);
        map.put("data", inventoryList);
        return map;
    }

    /**
     * 调用存储过程，创建/更新其他出入库头信息
     *
     * @param operationOtherHeadDto
     * @return headId
     */
    @RequestMapping("/createHead")
    @ResponseBody
    public OperationOtherHeadDTO createHead(OperationOtherHeadDTO operationOtherHeadDto) {
        return otherService.createHead(operationOtherHeadDto);
    }

}